"""
Users API Routes
================

API endpoints for user management.
Handles user CRUD operations and profile management.
"""

from flask import Blueprint, request
from app.utils.jwt_handler import login_required
from app.utils.database import DatabaseManager
from app.models.user import User
from app.utils.response_formatter import format_response
from app import db

# Create users blueprint
users_bp = Blueprint('users', __name__)

# Initialize database manager
db_manager = DatabaseManager(db)

@users_bp.route('/', methods=['GET'])
@login_required
def get_users():
    """
    Get all users with pagination.
    
    Query Parameters:
        page: Page number (default: 1)
        per_page: Items per page (default: 10)
        search: Search term (optional)
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "Users retrieved successfully",
            "data": [...],
            "pagination": {...}
        }
    """
    try:
        # Get query parameters
        page = int(request.args.get('page', 1))
        per_page = int(request.args.get('per_page', 10))
        search = request.args.get('search', '').strip()
        
        # Validate pagination parameters
        if page < 1:
            page = 1
        if per_page < 1 or per_page > 100:
            per_page = 10
        
        # Build query
        query = User.query
        
        # Apply search filter if provided
        if search:
            search_filter = f"%{search}%"
            query = query.filter(
                User.username.ilike(search_filter) |
                User.email.ilike(search_filter) |
                User.first_name.ilike(search_filter) |
                User.last_name.ilike(search_filter)
            )
        
        # Get paginated results
        total = query.count()
        offset = (page - 1) * per_page
        users = query.offset(offset).limit(per_page).all()
        
        # Convert to dictionaries
        users_data = [user.to_dict() for user in users]
        
        return format_response(
            status='success',
            message='Users retrieved successfully',
            data=users_data,
            metadata={
                'pagination': {
                    'page': page,
                    'per_page': per_page,
                    'total': total,
                    'total_pages': (total + per_page - 1) // per_page,
                    'has_next': page < (total + per_page - 1) // per_page,
                    'has_prev': page > 1
                }
            }
        )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to retrieve users',
            error_code='internal_error',
            status_code=500
        )

@users_bp.route('/<int:user_id>', methods=['GET'])
@login_required
def get_user(user_id):
    """
    Get user by ID.
    
    Parameters:
        user_id: User ID
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "User retrieved successfully",
            "data": {...}
        }
    """
    try:
        # Get user from database
        user = db_manager.get_by_id(User, user_id)
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        return format_response(
            status='success',
            message='User retrieved successfully',
            data=user.to_dict()
        )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to retrieve user',
            error_code='internal_error',
            status_code=500
        )

@users_bp.route('/profile', methods=['GET'])
@login_required
def get_profile():
    """
    Get current user's profile.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "Profile retrieved successfully",
            "data": {...}
        }
    """
    try:
        # Get current user from request context
        current_user = request.current_user
        user_id = current_user.get('user_id')
        
        # Get user from database
        user = db_manager.get_by_id(User, user_id)
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        return format_response(
            status='success',
            message='Profile retrieved successfully',
            data=user.to_dict()
        )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to retrieve profile',
            error_code='internal_error',
            status_code=500
        )

@users_bp.route('/profile', methods=['PUT'])
@login_required
def update_profile():
    """
    Update current user's profile.
    
    Request Body:
        {
            "first_name": "string (optional)",
            "last_name": "string (optional)",
            "email": "string (optional)"
        }
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "Profile updated successfully",
            "data": {...}
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data:
            return format_response(
                status='error',
                message='Request body is required',
                error_code='missing_data',
                status_code=400
            )
        
        # Get current user
        current_user = request.current_user
        user_id = current_user.get('user_id')
        
        # Get user from database
        user = db_manager.get_by_id(User, user_id)
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        # Validate email if provided
        if 'email' in data:
            from app.utils.validators import validate_email
            is_valid, error = validate_email(data['email'])
            if not is_valid:
                return format_response(
                    status='error',
                    message='Invalid email format',
                    error_code='invalid_email',
                    data={'email': [error]},
                    status_code=400
                )
            
            # Check if email is already taken by another user
            existing_user = User.find_by_email(data['email'])
            if existing_user and existing_user.id != user_id:
                return format_response(
                    status='error',
                    message='Email is already taken',
                    error_code='email_taken',
                    status_code=400
                )
        
        # Validate names if provided
        if 'first_name' in data:
            from app.utils.validators import validate_name
            is_valid, error = validate_name(data['first_name'], 'First name')
            if not is_valid:
                return format_response(
                    status='error',
                    message='Invalid first name',
                    error_code='invalid_first_name',
                    data={'first_name': [error]},
                    status_code=400
                )
        
        if 'last_name' in data:
            from app.utils.validators import validate_name
            is_valid, error = validate_name(data['last_name'], 'Last name')
            if not is_valid:
                return format_response(
                    status='error',
                    message='Invalid last name',
                    error_code='invalid_last_name',
                    data={'last_name': [error]},
                    status_code=400
                )
        
        # Update user fields
        allowed_fields = ['first_name', 'last_name', 'email']
        update_data = {k: v for k, v in data.items() if k in allowed_fields and v is not None}
        
        if not update_data:
            return format_response(
                status='error',
                message='No valid fields to update',
                error_code='no_update_fields',
                status_code=400
            )
        
        # Update user
        if db_manager.update(user, update_data):
            return format_response(
                status='success',
                message='Profile updated successfully',
                data=user.to_dict()
            )
        else:
            return format_response(
                status='error',
                message='Failed to update profile',
                error_code='update_failed',
                status_code=500
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to update profile',
            error_code='internal_error',
            status_code=500
        )

@users_bp.route('/<int:user_id>', methods=['PUT'])
@login_required
def update_user(user_id):
    """
    Update user by ID (admin only).
    
    Parameters:
        user_id: User ID
    
    Request Body:
        {
            "first_name": "string (optional)",
            "last_name": "string (optional)",
            "email": "string (optional)",
            "is_active": "boolean (optional)"
        }
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "User updated successfully",
            "data": {...}
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data:
            return format_response(
                status='error',
                message='Request body is required',
                error_code='missing_data',
                status_code=400
            )
        
        # Get user from database
        user = db_manager.get_by_id(User, user_id)
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        # Update user fields
        allowed_fields = ['first_name', 'last_name', 'email', 'is_active']
        update_data = {k: v for k, v in data.items() if k in allowed_fields and v is not None}
        
        if not update_data:
            return format_response(
                status='error',
                message='No valid fields to update',
                error_code='no_update_fields',
                status_code=400
            )
        
        # Update user
        if db_manager.update(user, update_data):
            return format_response(
                status='success',
                message='User updated successfully',
                data=user.to_dict()
            )
        else:
            return format_response(
                status='error',
                message='Failed to update user',
                error_code='update_failed',
                status_code=500
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to update user',
            error_code='internal_error',
            status_code=500
        )

@users_bp.route('/<int:user_id>', methods=['DELETE'])
@login_required
def delete_user(user_id):
    """
    Delete user by ID (admin only).
    
    Parameters:
        user_id: User ID
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "User deleted successfully"
        }
    """
    try:
        # Get user from database
        user = db_manager.get_by_id(User, user_id)
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        # Delete user
        if db_manager.delete(user):
            return format_response(
                status='success',
                message='User deleted successfully'
            )
        else:
            return format_response(
                status='error',
                message='Failed to delete user',
                error_code='delete_failed',
                status_code=500
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Failed to delete user',
            error_code='internal_error',
            status_code=500
        )